package com.henry.chatkit.weight.gatherimage

import android.content.Context
import android.graphics.*
import android.text.TextUtils
import android.widget.ImageView
import com.blankj.utilcode.util.ThreadUtils
import com.henry.chatkit.R
import com.henry.chatkit.glide.GlideEngine
import com.henry.chatkit.Constants
import com.henry.chatkit.utils.EncryptUtils
import com.henry.chatkit.utils.ImageUtils
import java.io.File
import java.util.concurrent.ExecutionException


open class TeamHeadSynthesizer(var mContext: Context, var imageView: ImageView) : Synthesizer {

    // 当前多图合成的唯一ID，用来做缓存处理，以及判断合成图片是否需要变更，如果多个url有变动，currentTargetID也会发生变动，需要重新生成
    var currentTargetID: String? = null
    // 多图片数据
    var multiImageData: MultiImageData = MultiImageData()

    // 目标图片宽高
    var targetImageSize = 0
    // 最大宽度
    var maxWidth: Int = 0
    // 最大高度
    var maxHeight: Int = 0
    // 背景色
    var bgColor: Int = Color.parseColor("#cfd3d8")
    // 行数
    var mRowCount = 0
    // 列数
    var mColumnCount = 0
    // 宫格间距
    var gap = 2

    // 加载完毕
    var loadOk = false
    var imageId = ""

    fun setMaxWidthHeight(width: Int, height: Int) {
        this.maxWidth = width
        this.maxHeight = height
    }

    fun getDefaultImage(): Int {
        return multiImageData.defaultImageResId
    }
    
    fun setDefaultImage(defaultImageResId: Int) {
        multiImageData.defaultImageResId = defaultImageResId
    }

    /**
     * 设置宫格参数
     * @param imagesSize 图片数量
     * @return 宫格参数 gridParam[0] 宫格行数 gridParam[1] 宫格列数
     */
    private fun calculateGridParam(imagesSize: Int): IntArray {
        val gridParam = IntArray(2)
        when (imagesSize) {
            1, 2 -> {
                gridParam[0] = 1
                gridParam[1] = imagesSize
            }
            3, 4 -> {
                gridParam[0] = 2
                gridParam[1] = 2
            }
            else -> {
                gridParam[0] = imagesSize / 3 + if (imagesSize % 3 == 0) 0 else 1
                gridParam[1] = 3
            }
        }
        return gridParam
    }

    override fun synthesizeImageList(): Bitmap? {
        val mergeBitmap = Bitmap.createBitmap(maxWidth, maxHeight, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(mergeBitmap)
        drawDrawable(canvas)
        canvas.save()
        canvas.restore()
        return mergeBitmap
    }

    override fun asyncLoadImageList(): Boolean {
        val loadSuccess = true
        val imageUrls: List<Any>? = multiImageData.imageUrls
        if (imageUrls != null) {
            for (i in imageUrls.indices) {
                val defaultIcon = BitmapFactory.decodeResource(mContext.resources, R.drawable.default_head)
                //下载图片
                try {
                    val bitmap: Bitmap = syncLoadImage(imageUrls[i], targetImageSize)
                    multiImageData.putBitmap(bitmap, i);
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                    multiImageData.putBitmap(defaultIcon, i)
                } catch (e: ExecutionException) {
                    e.printStackTrace()
                    multiImageData.putBitmap(defaultIcon, i)
                }
            }
        }
        //下载完毕
        return loadSuccess
    }

    override fun drawDrawable(canvas: Canvas?) {
        //画背景
        canvas!!.drawColor(bgColor)
        //画组合图片
        val size = multiImageData.size()
        val topCenter: Int = (maxHeight + gap) / 2 //中间位置以下的顶点（有宫格间距）

        val bottomCenter: Int = (maxHeight - gap) / 2 //中间位置以上的底部（有宫格间距）

        val leftCenter: Int = (maxWidth + gap) / 2 //中间位置以右的左部（有宫格间距）

        val rightCenter: Int = (maxWidth - gap) / 2 //中间位置以左的右部（有宫格间距）

        val center = (maxHeight - targetImageSize) / 2 //中间位置以上顶部（无宫格间距）

        for (i in 0 until size) {
            val rowNum: Int = i / mColumnCount //当前行数
            val columnNum: Int = i % mColumnCount //当前列数
            val left = (targetImageSize * (if (mColumnCount == 1) columnNum + 0.5 else columnNum).toInt() + gap * (columnNum + 1))
            val top = (targetImageSize * (if (mColumnCount == 1) rowNum + 0.5 else rowNum).toInt() + gap * (rowNum + 1))
            val right = left + targetImageSize
            val bottom = top + targetImageSize
            val bitmap = multiImageData.getBitmap(i)
            when (size) {
                1 -> drawBitmapAtPosition(canvas, left, top, right, bottom, bitmap)
                2 -> drawBitmapAtPosition(canvas, left, center, right, center + targetImageSize, bitmap)
                3 -> {
                    if (i == 0) {
                        drawBitmapAtPosition(canvas, center, top, center + targetImageSize, bottom, bitmap)
                    } else {
                        drawBitmapAtPosition(canvas, gap * i + targetImageSize * (i - 1), topCenter, gap * i + targetImageSize * i, topCenter + targetImageSize, bitmap)
                    }
                }
                4 -> drawBitmapAtPosition(canvas, left, top, right, bottom, bitmap)
                5 -> {
                    when (i) {
                        0 -> drawBitmapAtPosition(canvas, rightCenter - targetImageSize, rightCenter - targetImageSize, rightCenter, rightCenter, bitmap)
                        1 -> drawBitmapAtPosition(canvas, leftCenter, rightCenter - targetImageSize, leftCenter + targetImageSize, rightCenter, bitmap)
                        else -> drawBitmapAtPosition(canvas, gap * (i - 1) + targetImageSize * (i - 2), topCenter, gap * (i - 1) + targetImageSize * (i - 1), topCenter + targetImageSize, bitmap)
                    }
                }
                6 -> {
                    if (i < 3) {
                        drawBitmapAtPosition(canvas, gap * (i + 1) + targetImageSize * i, bottomCenter - targetImageSize, gap * (i + 1) + targetImageSize * (i + 1), bottomCenter, bitmap)
                    } else {
                        drawBitmapAtPosition(canvas, gap * (i - 2) + targetImageSize * (i - 3), topCenter, gap * (i - 2) + targetImageSize * (i - 2), topCenter + targetImageSize, bitmap)
                    }
                }
                7 -> {
                    when (i) {
                        0 -> drawBitmapAtPosition(canvas, center, gap, center + targetImageSize, gap + targetImageSize, bitmap)
                        1, 2, 3 -> drawBitmapAtPosition(canvas, gap * i + targetImageSize * (i - 1), center, gap * i + targetImageSize * i, center + targetImageSize, bitmap)
                        else -> drawBitmapAtPosition(canvas, gap * (i - 3) + targetImageSize * (i - 4), topCenter + targetImageSize / 2, gap * (i - 3) + targetImageSize * (i - 3), topCenter + targetImageSize / 2 + targetImageSize, bitmap)
                    }
                }
                8 -> {
                    when (i) {
                        0 -> drawBitmapAtPosition(canvas, rightCenter - targetImageSize, gap, rightCenter, gap + targetImageSize, bitmap)
                        1 -> drawBitmapAtPosition(canvas, leftCenter, gap, leftCenter + targetImageSize, gap + targetImageSize, bitmap)
                        2, 3, 4, 5 -> drawBitmapAtPosition(canvas, gap * (i - 1) + targetImageSize * (i - 2), center, gap * (i - 1) + targetImageSize * (i - 1), center + targetImageSize, bitmap)
                        else -> drawBitmapAtPosition(canvas, gap * (i - 4) + targetImageSize * (i - 5), topCenter + targetImageSize / 2, gap * (i - 4) + targetImageSize * (i - 4), topCenter + targetImageSize / 2 + targetImageSize, bitmap)
                    }
                }
                9 -> drawBitmapAtPosition(canvas, left, top, right, bottom, bitmap)
            }
        }
    }

    /**
     * 根据坐标画图
     */
    private fun drawBitmapAtPosition(canvas: Canvas, left: Int, top: Int, right: Int, bottom: Int, bitmap: Bitmap?) {
        var aBitmap = bitmap
        if (aBitmap == null) {
            //图片为空用默认图片
            if (multiImageData.defaultImageResId > 0) {
                //设置过默认id
                aBitmap = BitmapFactory.decodeResource(mContext.resources, multiImageData.defaultImageResId)
            }
        }
        if (aBitmap != null) {
            val rect = Rect(left, top, right, bottom)
            canvas.drawBitmap(aBitmap, null, rect, null)
        }
    }

    /**
     * 同步加载图片
     */
    @Throws(ExecutionException::class, InterruptedException::class)
    private fun syncLoadImage(imageUrl: Any, targetImageSize: Int): Bitmap {
        return GlideEngine.loadBitmap(imageUrl, targetImageSize)
    }

    /**
     * 生成合成图片的id，保证唯一性
     */
    private fun buildTargetSynthesizedId(): String? {
        val size = multiImageData.size()
        val buffer = StringBuffer()
        for (i in 0 until size) {
            val imageUrl = multiImageData.imageUrls!![i]
            buffer.append(i.toString() + "" + imageUrl)
        }
        return EncryptUtils.getMD5String(buffer.toString())
    }

    fun load() {
        if (multiImageData.size() == 0) {
            imageView.setImageResource(multiImageData.defaultImageResId)
            return
        }

        if (multiImageData.size() == 1) {
            GlideEngine.loadImage(multiImageData.imageUrls?.get(0), imageView)
            return
        }

        val newTargetID = buildTargetSynthesizedId()
        if (loadOk && null != imageView.drawable && TextUtils.equals(currentTargetID, newTargetID)) {
            //两次加载的图片是一样的，而且已经加载成功了，图片没有被回收,此时无需重复加载
            return
        }
        currentTargetID = newTargetID
        //初始化图片信息
        val gridParam = calculateGridParam(multiImageData.size())
        mRowCount = gridParam[0]
        mColumnCount = gridParam[1]
        targetImageSize = (maxWidth - (mColumnCount + 1) * gap) / if (mColumnCount == 1) 2 else mColumnCount //图片尺寸

        //imageView.setImageResource(multiImageData.getDefaultImageResId());
        ThreadUtils.executeByCached(object : ThreadUtils.SimpleTask<Void>() {
            override fun doInBackground(): Void? {
                //根据id获取存储的文件路径
                val file = File(Constants.IMAGE_BASE_DIR + currentTargetID)
                var cacheBitmapExists = false
                if (file.exists() && file.isFile) {
                    //文件存在，加载到内存
                    val options = BitmapFactory.Options()
                    options.inJustDecodeBounds = true
                    BitmapFactory.decodeFile(file.path, options)
                    if (options.outWidth > 0 && options.outHeight > 0) {
                        //当前文件是图片
                        cacheBitmapExists = true
                    }
                }
                if (!cacheBitmapExists) {
                    // 收集图片
                    asyncLoadImageList()
                    // 合成图片
                    val bitmap = synthesizeImageList()
                    ImageUtils.storeBitmap(file, bitmap)
                    imageView.post { callback.onCall(bitmap, currentTargetID, true) }
                } else {
                    imageView.post { callback.onCall(file, currentTargetID, true) }
                }
                return null
            }

            override fun onSuccess(result: Void?) {

            }

        })
    }

    var callback: Callback = object : Callback {
        override fun onCall(obj: Any?, targetID: String?, complete: Boolean) {
            //判断回调结果的任务id是否为同一批次的任务
            if (!TextUtils.equals(currentTargetID, targetID)) {
                return
            }
            if (obj is File) {
                if (complete) {
                    loadOk = true
                }
                imageView.setImageBitmap(BitmapFactory.decodeFile(obj.absolutePath))
            } else if (obj is Bitmap) {
                if (complete) {
                    loadOk = true
                }
                imageView.setImageBitmap(obj as Bitmap?)
            }
        }
    }

    interface Callback {
        fun onCall(obj: Any?, targetID: String?, complete: Boolean)
    }

}